/* -*-c++-*- */
/* osgGIS - GIS Library for OpenSceneGraph
 * Copyright 2007-2008 Glenn Waldron and Pelican Ventures, Inc.
 * http://osggis.org
 *
 * osgGIS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef _OSGGIS_GEOCENTRIC_SPATIAL_REFERENCE_H_
#define _OSGGIS_GEOCENTRIC_SPATIAL_REFERENCE_H_ 1

#include <osgGIS/Common>
#include <osgGIS/SpatialReferenceBase>
#include <osgGIS/Ellipsoid>

namespace osgGIS
{
    /**
     * Spatial reference frame for data in earth-centered XYZ coordiantes (ECEF).
     */
    class GeocentricSpatialReference : public SpatialReferenceBase  
    {
    public:
        /**
         * Constructs a geocentric SRS.
         *
         * @param basis
         *      SRS from which this new SRS takes its reference ellipsoid.
         */
        GeocentricSpatialReference(
            const SpatialReference* basis );

        /**
         * Constructs a new geocentric SRS.
         *
         * @param basis
         *      SRS from which this new SRS takes its reference ellipsoid.
         * @param ref_frame
         *      Reference frame matrix that allows you to specify data that
         *      is inherently geocentric but has been transformed to a local
         *      origin.
         */
        GeocentricSpatialReference(
            const SpatialReference* basis,
            const osg::Matrixd& ref_frame );

    public: // SpatialReference methods  

        /**
         * Gets the well-known text string associated with the BASIS SRS.
         * Note that there actually is no WKT representation of a geocentric SRS,
         * so this just returns the WKT of the SRS from which this SRS derives
         * its reference ellipsoid.
         *
         * @return OGC WKT (well-known WKT) SRS representation
         */
		virtual const std::string& getWKT() const;

        /**
         * Always returns false, since this is a geocentric SRS.
         * @return false
         */
		virtual bool isGeographic() const;

        /**
         * Always returns false, since this is a geocentric SRS.
         * @return false
         */
		virtual bool isProjected() const;
		
        /**
         * Always returns true since this is a geocentric SRS.
         * @return true
         */
		virtual bool isGeocentric() const;
		
        /**
         * Gets the SRS from which this object derives its reference ellipsoid.
         * @return A geographic SRS
         */
		virtual const SpatialReference* getGeographicSRS() const;

        /**
         * Gets this object's reference ellipsoid, i.e. the approximate shape of
         * the earth that it uses to transform coordinates.
         *
         * @return An ellipsoid model
         */
        virtual const Ellipsoid& getEllipsoid() const;
		
        /**
         * Gets the readable name of this SRS.
         *
         * @return A human-readable string
         */
		virtual std::string getName() const;

        /**
         * Gets whether this and other SRS are mathematically equivalent.
         */
        virtual bool equivalentTo( const SpatialReference* rhs ) const;

        /**
         * Gets the optional reference frame matrix that you can use to generate
         * "localized" geocentric coordinates (i.e. earth-centered coordinates that
         * have been transformed to a local origin: LOCALIZED_P = P * REF_FRAME).
         */
        virtual const osg::Matrixd& getReferenceFrame() const;

        /**
         * Gets the optional reference frame matrix that you can use to de-localize
         * "localized" geocentric coordinates (i.e. earth-centered coordinates that
         * have been transformed to a local origin: P = LOCALIZED_P * INV_REF_FRAME).
         */
        virtual const osg::Matrixd& getInverseReferenceFrame() const;

        /**
         * Creates an exact copy of this SRS, and then applies a new reference frame
         * transform matrix to it.
         */
        virtual SpatialReference* cloneWithNewReferenceFrame( const osg::Matrixd& rf ) const;
		

    public: // SpatialReference methods

        /**
         * Returns a point transformed into this SRS.
         */
		virtual GeoPoint transform( const GeoPoint& input ) const;

        /** 
         * Transforms a point into this SRS (modifying the input data).
         */
        virtual bool transformInPlace( GeoPoint& input ) const;
		
        /**
         * Returns a shape transformed into this SRS.
         */
		virtual GeoShape transform( const GeoShape& input ) const;

        /**
         * Transforms a shape into this SRS (modifying the input data).
         */
        virtual bool transformInPlace( GeoShape& input ) const;
        
        
        virtual GeoExtent transform( const GeoExtent& input ) const;


    public:        
        
        virtual ~GeocentricSpatialReference();

    private:
        osg::ref_ptr<SpatialReference> basis;
        Ellipsoid ellipsoid;
    };
}

#endif // _OSGGIS_GEOCENTRIC_SPATIAL_REFERENCE_H_
